package cn.bonoon.controllers.role;

import java.util.Collections;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

import cn.bonoon.core.plugins.RoleService;
import cn.bonoon.entities.plugins.RoleEntity;
import cn.bonoon.kernel.config.SortableItem;
import cn.bonoon.kernel.events.DialogEvent;
import cn.bonoon.kernel.menus.ActionInfo;
import cn.bonoon.kernel.menus.ChannelInfo;
import cn.bonoon.kernel.menus.IModuleInfo;
import cn.bonoon.kernel.menus.MenuInfo;
import cn.bonoon.kernel.menus.TabInfo;
import cn.bonoon.kernel.menus.TabItem;
import cn.bonoon.kernel.support.services.IService;
import cn.bonoon.kernel.util.StringHelper;
import cn.bonoon.kernel.web.annotations.grid.GridStandardDefinition;
import cn.bonoon.kernel.web.controllers.AbstractGridController;
import cn.bonoon.kernel.web.handlers.DialogDetailHandler;
import cn.bonoon.kernel.web.handlers.DialogFormInitializer;
import cn.bonoon.kernel.web.handlers.DialogInsertHandler;
import cn.bonoon.kernel.web.handlers.DialogUpdateHandler;
import cn.bonoon.kernel.web.models.DialogModel;

@Controller
@RequestMapping("s/sys/role")
public class SuperRoleController extends AbstractGridController<RoleEntity, RoleItem> {
	private final RoleService service;

	@Autowired
	public SuperRoleController(RoleService service) {
		super(service);
		this.service = service;
	}

	@RequestMapping("!{key}/{module}!privileges.do")
	public String privileges(Model model, @PathVariable("key") String key, @PathVariable("module") String module, Long roleid) {
		List<String> selectedIds;
		if(null != roleid && roleid > 0){
			selectedIds = service.getPrivilegeMeunId(roleid);
		}else{
			selectedIds = Collections.emptyList();
		}
		StringBuilder html = new StringBuilder();
		parseHtml(html, module, selectedIds, roleid, false);
		model.addAttribute("privileges", html);
		model.addAttribute("layout", "layout-empty.vm");
		return "u-sys-role";
	}

	private class RoleFormInitializer implements DialogFormInitializer<RoleEntity> {
		@Override
		public Object init(IService<RoleEntity> is, DialogModel model, DialogEvent event, Long id, Object form) {
			String moduleKey = null; // 子系统
			RoleEditor editor = (RoleEditor)form;
			List<String> selectedIds;
			if(null != editor){
				moduleKey = editor.getModuleKey();
				selectedIds = service.getPrivilegeMeunId(id);
			}else{
				selectedIds = Collections.emptyList(); // 已选中的权限
			}
			
			StringBuilder modules = new StringBuilder();
			for (IModuleInfo m : moduleManager.modules()) {// 获取所有子系统
				String mk = m.getId();
				modules.append("<option");
				if (StringHelper.isEmpty(moduleKey) && null == id) {
					moduleKey = mk;
				}else if(mk.equals(moduleKey)){
					modules.append(" selected='selected'");
				}
				modules.append(" value='").append(mk).append("'>").append(m.getName()) .append("</option>");
			}
			
			model.addObject("id", id);
			model.addObject("moduleKey", modules);
			StringBuilder html = new StringBuilder("<div id='div-privileges'>");
			parseHtml(html, moduleKey, selectedIds, id, false);
			html.append("</div>");
			model.addObject("privileges", html);
			return form;
		}
	}
	
	private class RoleDetailInitializer implements DialogFormInitializer<RoleEntity> {
		@Override
		public Object init(IService<RoleEntity> is, DialogModel model, DialogEvent event, Long id, Object form) {
			RoleDetail detail = (RoleDetail)form;
			String moduleKey = detail.getModuleKey(); // 子系统
			List<String> selectedIds = service.getPrivilegeMeunId(id);
			StringBuilder html = new StringBuilder();
			parseHtml(html, moduleKey, selectedIds, id, true);
			detail.setPrivileges(html.toString());
			return form;
		}
	}

	private void parseHtml(StringBuilder html, String key, List<String> selectedIds, Long roleId, boolean readonly) {
		IModuleInfo mi = moduleManager.module(key); // 获取子系统
		
		if(null != mi){
			html.append("<div style='width:100%;height:300px;overflow-y:scroll;margin:0;padding:0;'><table width='90%' class='editor'>");
			html.append("<tbody id='role-privilege-editor'><tr><td>");
			
			html.append(mi.getName());
			if (!readonly) {			
				html.append("<div style='color:#FF0000;font-size:11px;padding-left:5px;'>（提示：“全选”-选中菜单以及所有子级菜单；“取消”-取消选中菜单以及所有子级菜单。）</div>");
			}
			html.append("</td></tr>");
			int i = 1;
			for (ChannelInfo ci : mi.getChannels()) { // 循环该子系统下的所有频度
				String checkboxClass = "C" + i++;
				html.append("<tr><td style='padding-left:30px;'>");
				__checked(html, ci.getId(), selectedIds, checkboxClass, readonly);
				//html.append(ci.getName());
				__name(html, ci);
				
				visitMenus(ci.getMenus(), html, selectedIds, 2, checkboxClass, roleId, readonly); // 递归该频度下所有菜单
				
				//TODO tabs
				int j = 1;
				for(TabInfo ti : ci.getTabs()){
					String cbcls = checkboxClass + '-' + j++;
					html.append("<tr><td style='padding-left:60px;'>").append(ti.getName());
					__button(html, cbcls, readonly);
					html.append("</td></tr>");
					for(TabItem item : ti.getItems()){
						String iid = item.getId();
						html.append("<tr><td style='padding-left:90px;'>");
						__checked(html, iid, selectedIds, cbcls, readonly);
						__name(html, item).append("</td></tr>");
					}
				}
				html.append("</td></tr>");
			}
			html.append("</tbody></table></div>");
		}
	}
	
	private StringBuilder __name(StringBuilder html, SortableItem item){
		html.append("<label for='").append(item.getId()).append("'>").append(item.getName()).append("</label>");
		return html;
	}
	
	private void __checked(StringBuilder html, boolean checked){
		html.append("<img src='");
		if(checked){
			html.append(toUrl("/res/images/checkedBox.png"));
		}else{
			html.append(toUrl("/res/images/notCheckBox.png"));
		}
		html.append("'/>");
	}
	
	private void __checked(StringBuilder html, String mid, List<String> selected, String chkClss, boolean readonly) {
		if (readonly) {
			__checked(html, selected.contains(mid));
		} else {
			html.append("<input type='checkbox' class='").append(chkClss).append("' name='privileges' value='").append(mid);
			if(selected.contains(mid)){
				html.append("' checked='checked");
			}
			html.append("' id='").append(mid).append("'/>");
		}
	}

	private void visitMenus(List<MenuInfo> menus, StringBuilder html, List<String> selectedIds, final int deep, final String checkboxClass, Long roleId, boolean readonly) {
		if (null == menus || menus.isEmpty()) { return; }
		__button(html, checkboxClass, readonly);
		html.append("</td></tr>");
		int left = deep * 30, i = 1;
		for (MenuInfo mi : menus) {
			String chkClss = checkboxClass + "C" + i++;
			String mid = mi.getId();
			html.append("<tr><td style='padding-left:").append(left).append("px;'>");
			__checked(html, mid, selectedIds, chkClss, readonly);
			__name(html, mi);
			long actions = service.getActions(mid, roleId);
			
			ActionInfo[] actions_array = mi.getActions();
			if (null != actions_array && actions_array.length > 0) {
				html.append("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");
				for (ActionInfo action: actions_array) {
					int key = action.getKey();
					String key_actions = mid + "_actions";
					if (readonly) {
						__checked(html, (actions & key) == key);
					} else {
						html.append("<input type='checkbox' name='").append(key_actions).append("' class='").append(chkClss).append("' value='").append(key);
						if((actions & key) == key){
							html.append("' checked='checked");
						}
						html.append("' id='at_").append(action.getKey()).append("'/>");
					}
					//__name(html, action);
					//html.append(action.getName());
					html.append("<label for='at_").append(action.getKey()).append("'>").append(action.getName()).append("</label>");

				}
			}
			List<MenuInfo> smenus = mi.getMenus();
			visitMenus(smenus, html, selectedIds, deep + 1, chkClss, roleId, readonly);
		}
	}

	private void __button(StringBuilder html, final String cbcls, boolean readonly) {
		if(!readonly){
			html.append("<a style='padding-left:40px;' href='javascript:void(0);' name='privileges_allsel' class='").append(cbcls) .append("'>全选</a>");
			html.append("<span style='color:#bfbfbf;'>&nbsp;|&nbsp;</span><a href='javascript:void(0);' name='privileges_cancel' class='").append(cbcls) .append("'>取消</a>");
		}
	}

	@Override
	@GridStandardDefinition
	protected RoleService initLayoutGrid(LayoutGridRegister register) throws Exception {
		DialogInsertHandler<RoleEntity> dih = new DialogInsertHandler<RoleEntity>(register, service, RoleEditor.class);
		dih.setFormInitializer(new RoleFormInitializer());
		dih.register(register.toolbar()).ordinal(0);

		DialogDetailHandler<RoleEntity> ddh = new DialogDetailHandler<RoleEntity>(register, service, RoleDetail.class);
		ddh.setFormInitializer(new RoleDetailInitializer());
		ddh.register(register.button()).ordinal(0);
		
		DialogUpdateHandler<RoleEntity> duh = new DialogUpdateHandler<RoleEntity>(register, service, RoleEditor.class);
		duh.setFormInitializer(new RoleFormInitializer());
		duh.register(register.button()).ordinal(1);
		return service;
	}

	@Override
	protected Class<RoleItem> itemClass() {
		return RoleItem.class;
	}
}
